# Load in data
hires_2019_clean <- read_csv('../clean_data/hires_2019_clean.csv')
Rows: 124446 Columns: 19
── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (4): start_station_name, start_station_description, end_station_name, end_station_description
dbl (11): duration, start_station_id, start_station_latitude, start_station_longitude, end_station_id, end_station...
date (2): start_date, end_date
time (2): start_time, end_time
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
rain_2019_clean <- read_csv('../clean_data/rain_2019_clean.csv')
Rows: 365 Columns: 2
── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
dbl (1): rainfall_mm
date (1): start_date
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# visualising use by month
hires_2019_clean %>%
mutate(month = month(start_date, label = TRUE), .before = 1) %>%
group_by(month) %>%
summarise(count = n()) %>%
ggplot() +
aes(x = month, y = count) +
geom_col(fill = "#F27F1B") +
geom_text(aes(label = count), vjust = 2, colour = "white", size = 3.5) +
labs(x = "\nMonth",
y = "Number of journeys\n",
title = "Total number of bike journeys by month (2019)",
subtitle = "Total = 124446 journeys\n\n") +
scale_y_discrete(expand = c(0,1), limits = c(0, 5000, 10000, 15000)) +
theme_minimal() +
theme(title = element_text(size = 12),
axis.text = element_text(size = 10),
axis.title.x = element_text(size = 10),
axis.title.y = element_text(size = 10),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.background = element_blank(),
axis.line = element_line(colour = "black"))
Mapping out stations
# create smaller dataset for map
map_data <- hires_2019_clean %>%
select(start_station_longitude, start_station_latitude, start_station_id, start_station_name, start_elevation) %>%
distinct(start_station_id, .keep_all = TRUE)
# create custom icon for bike hire stations
bike <- makeIcon("../www/bicycle-outline.png")
# map station data using leaflet app
map_data %>%
leaflet() %>%
addProviderTiles(providers$CartoDB.Positron) %>%
addTiles(providers$CartoDB.Positron) %>%
addMarkers(~start_station_longitude, ~start_station_latitude,
icon = ~bike,
#clusterOptions = markerClusterOptions(),
popup = ~paste0("Station ID: ", start_station_id,
"<br>Name: ", start_station_name,
"<br>Elevation (m): ", start_elevation))
# addCircles(lng = ~start_station_longitude,
# lat = ~start_station_latitude,
# color = "#F27F1B",
# popup = ~paste0("Station ID: ", start_station_id,
# "<br>Name: ", start_station_name,
# "<br>Elevation (m): ", start_elevation))
Most popular stations
# top 10 start and end stations
hires_2019_clean %>%
select(start_station_id, start_station_name, start_station_description, start_elevation) %>%
count(start_station_id, start_station_name, start_station_description, start_elevation) %>%
arrange(desc(n)) %>%
head(10)
hires_2019_clean %>%
select(end_station_id, end_station_name, end_station_description, end_elevation) %>%
count(end_station_id, end_station_name, end_station_description, end_elevation) %>%
arrange(desc(n)) %>%
head(10)

# map most popular stations data using leaflet app
map_data %>%
filter(start_station_id %in% c("248", "259", "265", "289", "257",
"249", "247", "171", "183", "262",
"250", "358", "258")) %>%
leaflet() %>%
addProviderTiles(providers$CartoDB.Positron) %>%
addTiles(providers$CartoDB.Positron) %>%
addMarkers(~start_station_longitude, ~start_station_latitude,
icon = ~bike,
popup = ~paste0("Station ID: ", start_station_id,
"<br>Name: ", start_station_name,
"<br>Elevation (m): ", start_elevation))
NA
map_data
Error: object 'map_data' not found
hires_2019_clean %>%
select(start_station_id, end_station_id) %>%
filter(start_station_id == c("248", "259", "265", "289", "257", "262", "249", "247", "171", "183"),
end_station_id == c("262", "257", "250", "265", "248", "358", "259", "183", "171", "258")) %>%
chordDiagram(scale = TRUE)
hires_2019_clean %>%
select(start_station_id, end_station_id) %>%
filter(start_station_id == c("248", "259", "265", "289", "257", "262", "249", "247", "171", "183"),
end_station_id == c("262", "257", "250", "265", "248", "358", "259", "183", "171", "258")) %>%
ggraph(layout = "linear") +
geom_edge_arc(edge_colour = "black", edge_alpha = 0.3, edge_width = 0.2) +
geom_node_point(color = "#F27F1B", size = 10) +
geom_node_text(aes(label = name), repel = FALSE, size = 3, nudge_y = 0, colour = "white") +
labs(title = "Journeys between most popular stations\n\n") +
theme_void() +
theme(title = element_text(size = 12),
legend.position = "none",
plot.margin = unit(rep(1, 4), "cm"))
Journeys based on elevation
68622 downhill journeys 43774 uphill journeys 12050 flat journeys
12050 / 124446 * 100
[1] 9.682915
get_elev_raster()
Journeys based on weather
According to www.statista.com “A rainday is when one millimetre or
more of rain occurs in a day.” Based on this I have classified rainy
days as days where rainfall as recorded by www.power.larc.nasa.gov/ was
equal to or over 1mm in Edinburgh.

Hypothesis Test
# calculate the p-value and compare to α value
p_value <- null_distribution %>%
get_p_value(obs_stat = observed_stat, direction = "left")
Warning: Please be cautious in reporting a p-value of 0. This result is an approximation based on the number of `reps` chosen in the `generate()` step. See `?get_p_value()` for more information.
# hypothesis test
# α = 0.05
# H0 - Rain makes no difference to bike hires
# H1 - Rain has an impact on bike hires
# Type of test is one-sample proportion, right-sided.
#
# p value = 0
#
# The p-value being near to 0 means it is less than α, and so we should reject H0 based on our data. The result is statistically significant in favour of H1, that rain may impact bike hire numbers.
# rain_day <- hires_2019_clean %>%
# group_by(start_date) %>%
# mutate(rain_day = rainfall_mm >= 1) %>%
# select(start_date, rain_day) %>%
# count(start_date, rain_day)
#
# null_distribution <- rain_day %>%
# specify(response = rain_day, success = "TRUE") %>%
# hypothesize(null = "point", p = 0.05) %>%
# generate(reps = 10000, type = "draw") %>%
# calculate(stat = "prop")
#
# obs_stat <- rain_day %>%
# specify(response = rain_day, success = "TRUE") %>%
# calculate(stat = "prop")
#
# null_distribution %>%
# visualise() +
# shade_p_value(direction = "right", obs_stat = obs_stat)
#
# null_distribution %>%
# get_p_value(direction = "right", obs_stat = obs_stat)
# bootstrapped hypothesis
# α = 0.05
# H0 - Rain makes no difference to bike hires
# H1 - Rain has an impact on bike hires
# rain_day_flag <- rain_day %>%
# mutate(rain_day_flag = if_else(rain_day == "TRUE", 1, 0))
#
# null_distribution <- rain_day_flag %>%
# specify(response = rain_day_flag) %>%
# hypothesize(null = "point", mu = 0.05) %>%
# generate(reps = 10000, type = "bootstrap") %>%
# calculate(stat = "mean")
#
# null_distribution %>%
# visualise() +
# shade_p_value(direction = "right", obs_stat = obs_stat)
#
# null_distribution %>%
# get_p_value(direction = "right", obs_stat = obs_stat)
Independence Hypothesis Test On Rainy day data
Does a rainy day have an effect on bike hires
α = 0.05 H0 - Rain makes no difference to bike hires H1 - Rain has an
impact on bike hires
The p-value ≤ α, so I reject the null hypothesis H0 in favour of the
alternative hypothesis H1, that rain may have an effect on bike
hires.
Rainy Days in 2019 = 181 Rainy journeys = 58073 (46.7%) Non rainy
journeys = 66373 (53.3%)
66373 / 124446 * 100
[1] 53.33478
Time of Day analysis
Gym Bunnies - before 7am: 7783 23.07 mins
Morning Commuters - 7am to 9am: 12452 17.87 mins
Day Trippers - 9am to 5pm: 66880 29.75 mins
Homeward Bounders - 5pm to 6.30pm: 14961 23.86 mins
Evening Movers - 6.30pm to 10pm: 16815 23.5 mins
Pub Ponies - 10pm to Midnight: 5555 20.67 mins
Average journey time overall is 26.18 minutes
# Gym Bunnies - before 7am
hires_2019_clean %>%
mutate(start_time = as.character(start_time), end_time = as.character(end_time)) %>%
filter(start_time <= "07:00:00") %>%
mutate(mean_duration = round(mean(duration), 2)) %>%
count(mean_duration)
# Morning Commuters - 7am to 9am
hires_2019_clean %>%
mutate(start_time = as.character(start_time), end_time = as.character(end_time)) %>%
filter(start_time > "07:00:00", start_time <= "09:00:00") %>%
mutate(mean_duration = round(mean(duration), 2)) %>%
count(mean_duration)
# Day Trippers - 9am to 5pm
hires_2019_clean %>%
mutate(start_time = as.character(start_time), end_time = as.character(end_time)) %>%
filter(start_time > "09:00:00", start_time < "17:00:00") %>%
mutate(mean_duration = round(mean(duration), 2)) %>%
count(mean_duration)
# Homeward Bounders - 5pm to 6.30pm
hires_2019_clean %>%
mutate(start_time = as.character(start_time), end_time = as.character(end_time)) %>%
filter(start_time >= "17:00:00", start_time <= "18:30:00") %>%
mutate(mean_duration = round(mean(duration), 2)) %>%
count(mean_duration)
# Evening Movers - 6.30pm to 10pm
hires_2019_clean %>%
mutate(start_time = as.character(start_time), end_time = as.character(end_time)) %>%
filter(start_time > "18:30:00", start_time < "22:00:00") %>%
mutate(mean_duration = round(mean(duration), 2)) %>%
count(mean_duration)
# Pub Ponies - 10pm to Midnight
hires_2019_clean %>%
mutate(start_time = as.character(start_time), end_time = as.character(end_time)) %>%
filter(start_time >= "22:00:00") %>%
mutate(mean_duration = round(mean(duration), 2)) %>%
count(mean_duration)
# Average journey length
hires_2019_clean %>%
mutate(mean_duration = round(mean(duration), 2)) %>%
count(mean_duration)
NA
hires_2019_clean %>%
select(start_time) %>%
group_by(start_time) %>%
count() %>%
ggplot() +
geom_line(aes(start_time, n), col = "#F27F1B") +
labs(x = "\nTime of Day",
y = "Number of Journeys\n",
title = "Start time of journeys") +
theme_minimal() +
theme(title = element_text(size = 12),
axis.text = element_text(size = 10),
axis.title.x = element_text(size = 10),
axis.title.y = element_text(size = 10),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.background = element_blank(),
axis.line = element_line(colour = "black"))

# trying a raster image of elevation
ggplot() +
geom_raster(data = new_elevation_raster, aes(x = x, y = y)) +
geom_sf(data = elevation_raster, color = "white") +
coord_sf() +
scale_fill_viridis_c() +
labs(title = " ", x = " ", y = " ", fill = " ")
LS0tCnRpdGxlOiAiRmluYWwgUHJvamVjdCB3b3JrYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCmVkaXRvcl9vcHRpb25zOiAKICBjaHVua19vdXRwdXRfdHlwZTogaW5saW5lCi0tLQoKYGBge3IgaW5jbHVkZT1GQUxTRX0KIyBsb2FkIGxpYnJhcmllcwpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShqYW5pdG9yKQpsaWJyYXJ5KGhlcmUpCmxpYnJhcnkobHVicmlkYXRlKQpsaWJyYXJ5KGxlYWZsZXQpCmxpYnJhcnkoZWxldmF0cikKbGlicmFyeShyZ2RhbCkKbGlicmFyeShjaXJjbGl6ZSkKbGlicmFyeShnZ3JhcGgpCmxpYnJhcnkoaW5mZXIpCmxpYnJhcnkoc2YpCmxpYnJhcnkocmdlb2JvdW5kYXJpZXMpCmxpYnJhcnkobWFwZGVjaykKCmBgYAoKYGBge3IgbWVzc2FnZT1GQUxTRX0KIyBMb2FkIGluIGRhdGEKaGlyZXNfMjAxOV9jbGVhbiA8LSByZWFkX2NzdignLi4vY2xlYW5fZGF0YS9oaXJlc18yMDE5X2NsZWFuLmNzdicpCnJhaW5fMjAxOV9jbGVhbiA8LSByZWFkX2NzdignLi4vY2xlYW5fZGF0YS9yYWluXzIwMTlfY2xlYW4uY3N2JykKCgpgYGAKCgoKYGBge3J9CiMgbnVtYmVyIG9mIHN0YXRpb25zIGluIHRvdGFsOiAxNjQKaGlyZXNfMjAxOV9jbGVhbiAlPiUgCiAgZGlzdGluY3Qoc3RhcnRfc3RhdGlvbl9pZCkgJT4lIAogIGNvdW50KCkKCmhpcmVzXzIwMTlfY2xlYW4gJT4lIAogIGRpc3RpbmN0KGVuZF9zdGF0aW9uX2lkKSAlPiUgCiAgY291bnQoKQpgYGAKCgpgYGB7cn0KIyB2aXN1YWxpc2luZyB1c2UgYnkgbW9udGgKaGlyZXNfMjAxOV9jbGVhbiAlPiUgCiAgbXV0YXRlKG1vbnRoID0gbW9udGgoc3RhcnRfZGF0ZSwgbGFiZWwgPSBUUlVFKSwgLmJlZm9yZSA9IDEpICU+JSAKICBncm91cF9ieShtb250aCkgJT4lIAogIHN1bW1hcmlzZShjb3VudCA9IG4oKSkgJT4lCiAgZ2dwbG90KCkgKwogIGFlcyh4ID0gbW9udGgsIHkgPSBjb3VudCkgKwogIGdlb21fY29sKGZpbGwgPSAiI0YyN0YxQiIpICsKICBnZW9tX3RleHQoYWVzKGxhYmVsID0gY291bnQpLCB2anVzdCA9IDIsIGNvbG91ciA9ICJ3aGl0ZSIsIHNpemUgPSAzLjUpICsKICBsYWJzKHggPSAiXG5Nb250aCIsCiAgICAgICB5ID0gIk51bWJlciBvZiBqb3VybmV5c1xuIiwKICAgICAgIHRpdGxlID0gIlRvdGFsIG51bWJlciBvZiBiaWtlIGpvdXJuZXlzIGJ5IG1vbnRoICgyMDE5KSIsCiAgICAgICBzdWJ0aXRsZSA9ICJUb3RhbCA9IDEyNDQ0NiBqb3VybmV5c1xuXG4iKSArCiAgc2NhbGVfeV9kaXNjcmV0ZShleHBhbmQgPSBjKDAsMSksIGxpbWl0cyA9IGMoMCwgNTAwMCwgMTAwMDAsIDE1MDAwKSkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUodGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgICAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwKICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwKICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwKICAgICAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksIAogICAgICAgIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiYmxhY2siKSkKCmBgYAoKYGBge3J9CiMgdmlzdWFsaXNlIHVzZSBieSBkYXkgb2YgdGhlIHdlZWsKCmhpcmVzXzIwMTlfY2xlYW4gJT4lIAogIG11dGF0ZShkYXkgPSB3ZGF5KHN0YXJ0X2RhdGUsIGxhYmVsID0gVFJVRSksIC5iZWZvcmUgPSAxKSAlPiUgCiAgZ3JvdXBfYnkoZGF5KSAlPiUgCiAgc3VtbWFyaXNlKGNvdW50ID0gbigpKSAlPiUKICBnZ3Bsb3QoKSArCiAgYWVzKHggPSBkYXksIHkgPSBjb3VudCkgKwogIGdlb21fY29sKGZpbGwgPSAiI0YyN0YxQiIpICsKICBnZW9tX3RleHQoYWVzKGxhYmVsID0gY291bnQpLCB2anVzdCA9IDIsIGNvbG91ciA9ICJ3aGl0ZSIsIHNpemUgPSAzLjUpICsKICBsYWJzKHggPSAiXG5EYXkgb2Ygd2VlayIsCiAgICAgICB5ID0gIk51bWJlciBvZiBqb3VybmV5c1xuIiwKICAgICAgIHRpdGxlID0gIlRvdGFsIG51bWJlciBvZiBiaWtlIGpvdXJuZXlzIGJ5IGRheSBvZiB3ZWVrICgyMDE5KSIpICsKICBzY2FsZV95X2Rpc2NyZXRlKGV4cGFuZCA9IGMoMCwxKSwgbGltaXRzID0gYygwLCA1MDAwLCAxMDAwMCwgMTUwMDApKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZSh0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpLAogICAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApLAogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApLAogICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApLAogICAgICAgIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksIAogICAgICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwgCiAgICAgICAgYXhpcy5saW5lID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJibGFjayIpKQpgYGAKCgojIyMgTWFwcGluZyBvdXQgc3RhdGlvbnMKCmBgYHtyfQojIGNyZWF0ZSBzbWFsbGVyIGRhdGFzZXQgZm9yIG1hcAptYXBfZGF0YSA8LSBoaXJlc18yMDE5X2NsZWFuICU+JSAKICBzZWxlY3Qoc3RhcnRfc3RhdGlvbl9sb25naXR1ZGUsIHN0YXJ0X3N0YXRpb25fbGF0aXR1ZGUsIHN0YXJ0X3N0YXRpb25faWQsIHN0YXJ0X3N0YXRpb25fbmFtZSwgc3RhcnRfZWxldmF0aW9uKSAlPiUgCiAgZGlzdGluY3Qoc3RhcnRfc3RhdGlvbl9pZCwgLmtlZXBfYWxsID0gVFJVRSkKYGBgCgoKYGBge3J9CgojIGNyZWF0ZSBjdXN0b20gaWNvbiBmb3IgYmlrZSBoaXJlIHN0YXRpb25zCmJpa2UgIDwtICBtYWtlSWNvbigiLi4vd3d3L2JpY3ljbGUtb3V0bGluZS5wbmciKQoKIyBtYXAgc3RhdGlvbiBkYXRhIHVzaW5nIGxlYWZsZXQgYXBwCm1hcF9kYXRhICU+JSAKICBsZWFmbGV0KCkgJT4lIAogIGFkZFByb3ZpZGVyVGlsZXMocHJvdmlkZXJzJENhcnRvREIuUG9zaXRyb24pICU+JSAKICBhZGRUaWxlcyhwcm92aWRlcnMkQ2FydG9EQi5Qb3NpdHJvbikgJT4lCiAgYWRkTWFya2Vycyh+c3RhcnRfc3RhdGlvbl9sb25naXR1ZGUsIH5zdGFydF9zdGF0aW9uX2xhdGl0dWRlLCAKICAgICAgICAgICAgIGljb24gPSB+YmlrZSwKICAgICAgICAgICAgICNjbHVzdGVyT3B0aW9ucyA9IG1hcmtlckNsdXN0ZXJPcHRpb25zKCksCiAgICAgICAgICAgICBwb3B1cCA9IH5wYXN0ZTAoIlN0YXRpb24gSUQ6ICIsIHN0YXJ0X3N0YXRpb25faWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI8YnI+TmFtZTogIiwgc3RhcnRfc3RhdGlvbl9uYW1lLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiPGJyPkVsZXZhdGlvbiAobSk6ICIsIHN0YXJ0X2VsZXZhdGlvbikpCgogICMgYWRkQ2lyY2xlcyhsbmcgPSB+c3RhcnRfc3RhdGlvbl9sb25naXR1ZGUsCiAgIyAgICAgICAgICAgIGxhdCA9IH5zdGFydF9zdGF0aW9uX2xhdGl0dWRlLAogICMgICAgICAgICAgICBjb2xvciA9ICIjRjI3RjFCIiwKICAjICAgICAgICAgICAgcG9wdXAgPSB+cGFzdGUwKCJTdGF0aW9uIElEOiAiLCBzdGFydF9zdGF0aW9uX2lkLAogICMgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjxicj5OYW1lOiAiLCBzdGFydF9zdGF0aW9uX25hbWUsCiAgIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAiPGJyPkVsZXZhdGlvbiAobSk6ICIsIHN0YXJ0X2VsZXZhdGlvbikpCmBgYAoKIyMjIE1vc3QgcG9wdWxhciBzdGF0aW9ucwoKCmBgYHtyfQojIHRvcCAxMCBzdGFydCBhbmQgZW5kIHN0YXRpb25zCmhpcmVzXzIwMTlfY2xlYW4gJT4lIAogIHNlbGVjdChzdGFydF9zdGF0aW9uX2lkLCBzdGFydF9zdGF0aW9uX25hbWUsIHN0YXJ0X3N0YXRpb25fZGVzY3JpcHRpb24sIHN0YXJ0X2VsZXZhdGlvbikgJT4lIAogIGNvdW50KHN0YXJ0X3N0YXRpb25faWQsIHN0YXJ0X3N0YXRpb25fbmFtZSwgc3RhcnRfc3RhdGlvbl9kZXNjcmlwdGlvbiwgc3RhcnRfZWxldmF0aW9uKSAlPiUgCiAgYXJyYW5nZShkZXNjKG4pKSAlPiUgCiAgaGVhZCgxMCkKCmhpcmVzXzIwMTlfY2xlYW4gJT4lIAogIHNlbGVjdChlbmRfc3RhdGlvbl9pZCwgZW5kX3N0YXRpb25fbmFtZSwgZW5kX3N0YXRpb25fZGVzY3JpcHRpb24sIGVuZF9lbGV2YXRpb24pICU+JSAKICBjb3VudChlbmRfc3RhdGlvbl9pZCwgZW5kX3N0YXRpb25fbmFtZSwgZW5kX3N0YXRpb25fZGVzY3JpcHRpb24sIGVuZF9lbGV2YXRpb24pICU+JSAKICBhcnJhbmdlKGRlc2MobikpICU+JQogIGhlYWQoMTApCmBgYAoKCmBgYHtyfQojIHJvdW5kIHRyaXAgdnMgYSB0byBiIGpvdXJuZXkKaGlyZXNfMjAxOV9jbGVhbiAlPiUgCiAgZmlsdGVyKHN0YXJ0X3N0YXRpb25faWQgPT0gZW5kX3N0YXRpb25faWQpICU+JSAKICBjb3VudCgpCgoxMTk0NCAvIDEyNDQ0NiAqIDEwMCAjIDkuNiUgb2Ygam91cm5leXMgd2VyZSByb3VuZCB0cmlwcwoKIyBtb3N0IHBvcHVsYXIgcm91bmQgdHJpcCBzdGF0aW9ucwpoaXJlc18yMDE5X2NsZWFuICU+JSAKICBmaWx0ZXIoc3RhcnRfc3RhdGlvbl9pZCA9PSBlbmRfc3RhdGlvbl9pZCkgJT4lIAogIGNvdW50KHN0YXJ0X3N0YXRpb25faWQpICU+JSAKICBhcnJhbmdlKGRlc2MobikpCgojIHZpc3VhbGlzZSByb3VuZCB0cmlwIHZzIG9uZSB3YXlzCmhpcmVzXzIwMTlfY2xlYW4gJT4lIAogIG11dGF0ZShyb3VuZF90cmlwcyA9IHN0YXJ0X3N0YXRpb25faWQgPT0gZW5kX3N0YXRpb25faWQpICU+JSAKICBjb3VudChyb3VuZF90cmlwcykgJT4lIAogIGdncGxvdCgpICsKICBhZXMocm91bmRfdHJpcHMsIG4pICsKICBnZW9tX2NvbChmaWxsID0gIiNGMjdGMUIiKSArCiAgbGFicyh4ID0gIlxuT25lIFdheSB2cyBSb3VuZCBUcmlwIiwKICAgICAgIHkgPSAiTnVtYmVyIG9mIGpvdXJuZXlzXG4iLAogICAgICAgdGl0bGUgPSAiT25lIFdheSB2cyBSb3VuZCBUcmlwIGpvdXJuZXlzIHRha2VuIikgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUodGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgICAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwKICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwKICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwKICAgICAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksIAogICAgICAgIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiYmxhY2siKSkKCmBgYAoKCmBgYHtyfQojIG1hcCBtb3N0IHBvcHVsYXIgc3RhdGlvbnMgZGF0YSB1c2luZyBsZWFmbGV0IGFwcAptYXBfZGF0YSAlPiUgCiAgZmlsdGVyKHN0YXJ0X3N0YXRpb25faWQgJWluJSBjKCIyNDgiLCAiMjU5IiwgIjI2NSIsICIyODkiLCAiMjU3IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIyNDkiLCAiMjQ3IiwgIjE3MSIsICIxODMiLCAiMjYyIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIyNTAiLCAiMzU4IiwgIjI1OCIpKSAlPiUKICBsZWFmbGV0KCkgJT4lIAogIGFkZFByb3ZpZGVyVGlsZXMocHJvdmlkZXJzJENhcnRvREIuUG9zaXRyb24pICU+JSAKICBhZGRUaWxlcyhwcm92aWRlcnMkQ2FydG9EQi5Qb3NpdHJvbikgJT4lCiAgYWRkTWFya2Vycyh+c3RhcnRfc3RhdGlvbl9sb25naXR1ZGUsIH5zdGFydF9zdGF0aW9uX2xhdGl0dWRlLCAKICAgICAgICAgICAgIGljb24gPSB+YmlrZSwKICAgICAgICAgICAgIHBvcHVwID0gfnBhc3RlMCgiU3RhdGlvbiBJRDogIiwgc3RhcnRfc3RhdGlvbl9pZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiPGJyPk5hbWU6ICIsIHN0YXJ0X3N0YXRpb25fbmFtZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiPGJyPkVsZXZhdGlvbiAobSk6ICIsIHN0YXJ0X2VsZXZhdGlvbikpCgpgYGAKCmBgYHtyfQptYXBfZGF0YSAlPiUgCiAgZmlsdGVyKHN0YXJ0X3N0YXRpb25faWQgJWluJSBjKCIyNDgiLCAiMjU5IiwgIjI2NSIsICIyODkiLCAiMjU3IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIyNDkiLCAiMjQ3IiwgIjE3MSIsICIxODMiLCAiMjYyIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIyNTAiLCAiMzU4IiwgIjI1OCIpKSAlPiUgCiAgZ2dwbG90KGxhYmVsID0gc3RhcnRfc3RhdGlvbl9pZCkgKwogIGdlb21fcG9pbnQoYWVzKHN0YXJ0X3N0YXRpb25faWQsIHN0YXJ0X2VsZXZhdGlvbikpICsKICB0aGVtZV9idygpICsKICBnZW9tX3RleHQoYWVzKHN0YXJ0X3N0YXRpb25faWQsIHN0YXJ0X2VsZXZhdGlvbiwgbGFiZWwgPSBzdGFydF9lbGV2YXRpb24sIGhqdXN0PS0wLjIsIHZqdXN0PTApKQoKYGBgCgpgYGB7cn0KbGlicmFyeShtYXBkZWNrKQoKc2V0X3Rva2VuKCJway5leUoxSWpvaWFtSTNOQ0lzSW1FaU9pSmpiRE40Tm01Mk9HTXdaM3BuTTJOeGRIaGxNVGh4YW5BMEluMC5pRk5jT2d1VTZya1VRRWhHcnVxU0JnIikgICMjIHNldCB5b3VyIG1hcGJveCB0b2tlbiBoZXJlCiNzZXRfdG9rZW4oInBrLmV5SjFJam9pYW1JM05DSXNJbUVpT2lKamJETjRObTUyT0dNd1ozcG5NMk54ZEhobE1UaHhhbkEwSW4wLmlGTmNPZ3VVNnJrVVFFaEdydXFTQmciKSAgIyMgc2V0IHlvdXIgbWFwYm94IHRva2VuIGhlcmUKCiNtYXBkZWNrX3Rva2VucygpCgpoaXJlc18yMDE5X2NsZWFuICU+JSAKZmlsdGVyKHN0YXJ0X3N0YXRpb25faWQgJWluJSBjKCIyNDgiKSkgJT4lIAogIG5hLm9taXQoKSAlPiUgCm1hcGRlY2soc3R5bGUgPSBtYXBkZWNrX3N0eWxlKCdkYXJrJyksIHBpdGNoID0gNDUsCiAgICAgICAgbG9jYXRpb24gPSBjKDU1Ljk0MiwgLTMuMTk5KSklPiUKICBhZGRfYXJjKAogICAgICBsYXllcl9pZCA9ICdhcmNfbGF5ZXInCiAgICAsIG9yaWdpbiA9IGMoInN0YXJ0X3N0YXRpb25fbG9uZ2l0dWRlIiwgInN0YXJ0X3N0YXRpb25fbGF0aXR1ZGUiKQogICAgLCBkZXN0aW5hdGlvbiA9IGMoImVuZF9zdGF0aW9uX2xvbmdpdHVkZSIsICJlbmRfc3RhdGlvbl9sYXRpdHVkZSIpCiAgICAsIHN0cm9rZV9mcm9tX29wYWNpdHkgPSAxMDAKICAgICwgc3Ryb2tlX3RvX29wYWNpdHkgPSAxMDAKICAgICwgc3Ryb2tlX3dpZHRoID0gMwogICAgLCBzdHJva2VfZnJvbSA9ICIjRjI3RjFCIgogICAgLCBzdHJva2VfdG8gPSAiI0YyN0YxQiIKICApCgojIjI1OSIsICIyNjUiLCAiMjg5IiwgIjI1NyIsICIyNDkiLCAiMjQ3IiwgIjE3MSIsICIxODMiLCAiMjYyIiwgIjI1MCIsICIzNTgiLCAiMjU4IgpgYGAKCgpgYGB7cn0KaGlyZXNfMjAxOV9jbGVhbiAlPiUgCiAgc2VsZWN0KHN0YXJ0X3N0YXRpb25faWQsIGVuZF9zdGF0aW9uX2lkKSAlPiUgCiAgZmlsdGVyKHN0YXJ0X3N0YXRpb25faWQgPT0gYygiMjQ4IiwgIjI1OSIsICIyNjUiLCAiMjg5IiwgIjI1NyIsICIyNjIiLCAiMjQ5IiwgIjI0NyIsICIxNzEiLCAiMTgzIiksIAogICAgICAgICBlbmRfc3RhdGlvbl9pZCA9PSBjKCIyNjIiLCAiMjU3IiwgIjI1MCIsICIyNjUiLCAiMjQ4IiwgIjM1OCIsICIyNTkiLCAiMTgzIiwgIjE3MSIsICIyNTgiKSkgJT4lIAogIGNob3JkRGlhZ3JhbShzY2FsZSA9IFRSVUUpCiAgCmBgYAoKYGBge3J9CiMgSm91cm5leXMgZW5kaW5nIGF0IFZpY3RvcmlhIFF1YXkKaGlyZXNfMjAxOV9jbGVhbiAlPiUgCiAgZmlsdGVyKGVuZF9zdGF0aW9uX2lkID09ICIyNTAiKSAlPiUgCiAgY291bnQoKQoKIyBKb3VybmV5cyBlbmRpbmcgYXQgVmljdG9yaWEgUXVheSwgYnkgc3RhcnQgc3RhdGlvbgpoaXJlc18yMDE5X2NsZWFuICU+JSAKICBmaWx0ZXIoZW5kX3N0YXRpb25faWQgPT0gIjI1MCIpICU+JSAKICBjb3VudChzdGFydF9zdGF0aW9uX2lkKSAlPiUgCiAgYXJyYW5nZShkZXNjKG4pKQoKIyBKb3VybmV5cyBlbmRpbmcgYXQgR2VvcmdlIFNxdWFyZSwgYnkgc3RhcnQgc3RhdGlvbgpoaXJlc18yMDE5X2NsZWFuICU+JSAKICBmaWx0ZXIoZW5kX3N0YXRpb25faWQgPT0gIjE3MSIpICU+JSAKICBjb3VudChzdGFydF9zdGF0aW9uX2lkKSAlPiUgCiAgYXJyYW5nZShkZXNjKG4pKQoKaGlyZXNfMjAxOV9jbGVhbiAlPiUgCiAgZmlsdGVyKHN0YXJ0X3N0YXRpb25faWQgPT0gIjI1OSIpICU+JSAKICBjb3VudChlbmRfc3RhdGlvbl9pZCkgJT4lIAogIGFycmFuZ2UoZGVzYyhuKSkKYGBgCgoKCmBgYHtyfQpoaXJlc18yMDE5X2NsZWFuICU+JSAKICBzZWxlY3Qoc3RhcnRfc3RhdGlvbl9pZCwgZW5kX3N0YXRpb25faWQpICU+JQogIGZpbHRlcihzdGFydF9zdGF0aW9uX2lkID09IGMoIjI0OCIsICIyNTkiLCAiMjY1IiwgIjI4OSIsICIyNTciLCAiMjYyIiwgIjI0OSIsICIyNDciLCAiMTcxIiwgIjE4MyIpLCAKICAgICAgICAgZW5kX3N0YXRpb25faWQgPT0gYygiMjYyIiwgIjI1NyIsICIyNTAiLCAiMjY1IiwgIjI0OCIsICIzNTgiLCAiMjU5IiwgIjE4MyIsICIxNzEiLCAiMjU4IikpICU+JSAKICBnZ3JhcGgobGF5b3V0ID0gImxpbmVhciIpICsgCiAgZ2VvbV9lZGdlX2FyYyhlZGdlX2NvbG91ciA9ICJibGFjayIsIGVkZ2VfYWxwaGEgPSAwLjMsIGVkZ2Vfd2lkdGggPSAwLjIpICsKICBnZW9tX25vZGVfcG9pbnQoY29sb3IgPSAiI0YyN0YxQiIsIHNpemUgPSAxMCkgKwogIGdlb21fbm9kZV90ZXh0KGFlcyhsYWJlbCA9IG5hbWUpLCByZXBlbCA9IEZBTFNFLCBzaXplID0gMywgbnVkZ2VfeSA9IDAsIGNvbG91ciA9ICJ3aGl0ZSIpICsKICBsYWJzKHRpdGxlID0gIkpvdXJuZXlzIGJldHdlZW4gbW9zdCBwb3B1bGFyIHN0YXRpb25zXG5cbiIpICsKICB0aGVtZV92b2lkKCkgKwogIHRoZW1lKHRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLAogICAgICAgIHBsb3QubWFyZ2luID0gdW5pdChyZXAoMSwgNCksICJjbSIpKQpgYGAKCgojIyMgSm91cm5leXMgYmFzZWQgb24gZWxldmF0aW9uCgo2ODYyMiBkb3duaGlsbCBqb3VybmV5cwo0Mzc3NCB1cGhpbGwgam91cm5leXMKMTIwNTAgZmxhdCBqb3VybmV5cwoKYGBge3J9CiMgZG93bmhpbGwgdnMgdXBoaWxsIHZzIGZsYXQgam91cm5leXMKIyBiYXNlZCBvbiBlbGV2YXRpb24gb2Ygc3RhcnQgYW5kIGVuZCBzdGF0aW9ucwoKIyA2ODYyMiBkb3duaGlsbCBqb3VybmV5cyA1NSUKaGlyZXNfMjAxOV9jbGVhbiAlPiUgCiAgZmlsdGVyKGVsZXZhdGlvbl9kaWZmIDwgMCkgJT4lIAogIGNvdW50KCkKCjY4NjIyIC8gMTI0NDQ2ICogMTAwCgojIDQzNzc0IHVwaGlsbCBqb3VybmV5cyAzNSUKaGlyZXNfMjAxOV9jbGVhbiAlPiUgCiAgZmlsdGVyKGVsZXZhdGlvbl9kaWZmID4gMCkgJT4lIAogIGNvdW50KCkKCjQzNzc0IC8gMTI0NDQ2ICogMTAwCgojIDEyMDUwIGZsYXQgam91cm5leXMgOS43JQpoaXJlc18yMDE5X2NsZWFuICU+JSAKICBmaWx0ZXIoZWxldmF0aW9uX2RpZmYgPT0gMCkgJT4lIAogIGNvdW50KCkKCjEyMDUwIC8gMTI0NDQ2ICogMTAwCmBgYApgYGB7cn0KZ2V0X2VsZXZfcmFzdGVyKCkKYGBgCgoKCiMjIyBKb3VybmV5cyBiYXNlZCBvbiB3ZWF0aGVyCgpBY2NvcmRpbmcgdG8gd3d3LnN0YXRpc3RhLmNvbSAiQSByYWluZGF5IGlzIHdoZW4gb25lIG1pbGxpbWV0cmUgb3IgbW9yZSBvZiByYWluIG9jY3VycyBpbiBhIGRheS4iIEJhc2VkIG9uIHRoaXMgSSBoYXZlIGNsYXNzaWZpZWQgcmFpbnkgZGF5cyBhcyBkYXlzIHdoZXJlIHJhaW5mYWxsIGFzIHJlY29yZGVkIGJ5IHd3dy5wb3dlci5sYXJjLm5hc2EuZ292LyB3YXMgZXF1YWwgdG8gb3Igb3ZlciAxbW0gaW4gRWRpbmJ1cmdoLgoKCmBgYHtyfQpoaXJlc18yMDE5X2NsZWFuICU+JSAKICBzZWxlY3Qoc3RhcnRfZGF0ZSwgcmFpbmZhbGxfbW0pICU+JSAKICBnZ3Bsb3QoKSArCiAgZ2VvbV9saW5lKGFlcyhzdGFydF9kYXRlLCByYWluZmFsbF9tbSksIGNvbCA9ICJibHVlIikgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDEsIGNvbD0iI0YyN0YxQiIpICsKICBsYWJzKHggPSAiXG5EYXRlIiwKICAgICAgIHkgPSAiUmFpbmZhbGwgKG1tKVxuIiwKICAgICAgIHRpdGxlID0gIkVkaW5idXJnaCdzIGRhaWx5IHJhaW5mYWxsIGluIDIwMTkiLAogICAgICAgc3VidGl0bGUgPSAiKE9yYW5nZSBsaW5lIGF0IDFtbSwgYWJvdmUgd2hpY2ggd2UgY2xhc3MgYXMgcmFpbnkgZGF5KVxuIikgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUodGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgICAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwKICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwKICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwKICAgICAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksIAogICAgICAgIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiYmxhY2siKSkKYGBgCgojIyMgSHlwb3RoZXNpcyBUZXN0CgpgYGB7cn0KIyBJbmRlcGVuZGVuY2UgSHlwb3RoZXNpcwojIM6xID0gMC4wNQojIEgwIC0gdXBoaWxsIGpvdXJuZXlzIG1ha2VzIG5vIGRpZmZlcmVuY2UgdG8gYmlrZSBoaXJlcwojIEgxIC0gdXBoaWxsIGpvdXJuZXlzIGhhdmUgYW4gaW1wYWN0IG9uIGJpa2UgaGlyZXMKCiMgb3JnYW5pc2UgdGhlIGRhdGEgc28gSSBoYXZlIGFuIHVwaGlsbCBjb2x1bW4gd2l0aCBhIGxvZ2ljYWwgb3V0cHV0IFRSVUUvRkFMU0UgaWYgdGhlIGVsZXZhdGlvbiBjaGFuZ2Ugd2FzIHBvc2l0aXZlCiMgYWxzbyBjb3VudCB0aGUgbnVtYmVyIG9mIGpvdXJuZXlzIHRoYXQgb2NjdXJyZWQgb24gZWFjaCBkYXkKdXBoaWxsIDwtIGhpcmVzXzIwMTlfY2xlYW4gJT4lCiAgZ3JvdXBfYnkoc3RhcnRfZGF0ZSkgJT4lIAogIG11dGF0ZSh1cGhpbGwgPSBlbGV2YXRpb25fZGlmZiA+IDApICU+JQogIHNlbGVjdChzdGFydF9kYXRlLCB1cGhpbGwpICU+JSAKICBjb3VudChzdGFydF9kYXRlLCB1cGhpbGwpCgojIGNyZWF0ZSBhIG51bGwgZGlzdHJpYnV0aW9uIHBlcm11dGluZyB0aGUgVHJ1ZSBhbmQgRmFsc2UgdmFsdWVzIG9uIHdoZXRoZXIgdGhlIGpvdXJuZXkgd2FzIHVwaGlsbCBvciBub3QKIyBkbyAxMGsgcmVwcyBhbmQgY2hlY2sgdGhlIGRpZmZlcmVuY2UgaW4gbWVhbnMgb2YgdGhlIGdyb3VwcwpudWxsX2Rpc3RyaWJ1dGlvbiA8LSB1cGhpbGwgJT4lIAogIHNwZWNpZnkobiB+IHVwaGlsbCkgJT4lCiAgaHlwb3RoZXNpemUobnVsbCA9ICJpbmRlcGVuZGVuY2UiKSAlPiUgCiAgZ2VuZXJhdGUocmVwcyA9IDEwMDAwLCB0eXBlID0gInBlcm11dGUiKSAlPiUgCiAgY2FsY3VsYXRlKHN0YXQgPSAiZGlmZiBpbiBtZWFucyIsIG9yZGVyID0gYygiVFJVRSIsICJGQUxTRSIpKSAKCiMgY3JlYXRlIGFuIG9ic2VydmVkIHN0YXQKb2JzZXJ2ZWRfc3RhdCA8LSB1cGhpbGwgJT4lIAogIHNwZWNpZnkobiB+IHVwaGlsbCkgJT4lCiAgY2FsY3VsYXRlKHN0YXQgPSAiZGlmZiBpbiBtZWFucyIsIG9yZGVyID0gYygiVFJVRSIsICJGQUxTRSIpKSAKCiMgcGxvdCBvYnNlcnZlZCBzdGF0IG9uIHRoZSBudWxsIGRpc3RyaWJ1dGlvbgpudWxsX2Rpc3RyaWJ1dGlvbiAlPiUKICB2aXN1YWxpc2UoKSArCiAgc2hhZGVfcF92YWx1ZShvYnNfc3RhdCA9IG9ic2VydmVkX3N0YXQsIGRpcmVjdGlvbiA9ICJsZWZ0IikKCiMgY2FsY3VsYXRlIHRoZSBwLXZhbHVlIGFuZCBjb21wYXJlIHRvIM6xIHZhbHVlCnBfdmFsdWUgPC0gbnVsbF9kaXN0cmlidXRpb24gJT4lCiAgZ2V0X3BfdmFsdWUob2JzX3N0YXQgPSBvYnNlcnZlZF9zdGF0LCBkaXJlY3Rpb24gPSAibGVmdCIpCgpwX3ZhbHVlCmBgYAoKCmBgYHtyfQojIGh5cG90aGVzaXMgdGVzdAojIM6xID0gMC4wNQojIEgwIC0gUmFpbiBtYWtlcyBubyBkaWZmZXJlbmNlIHRvIGJpa2UgaGlyZXMKIyBIMSAtIFJhaW4gaGFzIGFuIGltcGFjdCBvbiBiaWtlIGhpcmVzCiMgVHlwZSBvZiB0ZXN0IGlzIG9uZS1zYW1wbGUgcHJvcG9ydGlvbiwgcmlnaHQtc2lkZWQuCiMgCiMgcCB2YWx1ZSA9IDAgCiMgCiMgVGhlIHAtdmFsdWUgYmVpbmcgbmVhciB0byAwIG1lYW5zIGl0IGlzIGxlc3MgdGhhbiDOsSwgYW5kIHNvIHdlIHNob3VsZCByZWplY3QgSDAgYmFzZWQgb24gb3VyIGRhdGEuIFRoZSByZXN1bHQgaXMgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCBpbiBmYXZvdXIgb2YgSDEsIHRoYXQgcmFpbiBtYXkgaW1wYWN0IGJpa2UgaGlyZSBudW1iZXJzLgoKIyByYWluX2RheSA8LSBoaXJlc18yMDE5X2NsZWFuICU+JQojICAgZ3JvdXBfYnkoc3RhcnRfZGF0ZSkgJT4lIAojICAgbXV0YXRlKHJhaW5fZGF5ID0gcmFpbmZhbGxfbW0gPj0gMSkgJT4lIAojICAgc2VsZWN0KHN0YXJ0X2RhdGUsIHJhaW5fZGF5KSAlPiUgCiMgICBjb3VudChzdGFydF9kYXRlLCByYWluX2RheSkKIyAKIyBudWxsX2Rpc3RyaWJ1dGlvbiA8LSByYWluX2RheSAlPiUKIyAgIHNwZWNpZnkocmVzcG9uc2UgPSByYWluX2RheSwgc3VjY2VzcyA9ICJUUlVFIikgJT4lCiMgICBoeXBvdGhlc2l6ZShudWxsID0gInBvaW50IiwgcCA9IDAuMDUpICU+JQojICAgZ2VuZXJhdGUocmVwcyA9IDEwMDAwLCB0eXBlID0gImRyYXciKSAlPiUKIyAgIGNhbGN1bGF0ZShzdGF0ID0gInByb3AiKQojIAojIG9ic19zdGF0IDwtIHJhaW5fZGF5ICU+JQojICAgc3BlY2lmeShyZXNwb25zZSA9IHJhaW5fZGF5LCBzdWNjZXNzID0gIlRSVUUiKSAlPiUKIyAgIGNhbGN1bGF0ZShzdGF0ID0gInByb3AiKQojIAojIG51bGxfZGlzdHJpYnV0aW9uICU+JQojICAgdmlzdWFsaXNlKCkgKwojICAgc2hhZGVfcF92YWx1ZShkaXJlY3Rpb24gPSAicmlnaHQiLCBvYnNfc3RhdCA9IG9ic19zdGF0KQojIAojIG51bGxfZGlzdHJpYnV0aW9uICU+JQojICAgZ2V0X3BfdmFsdWUoZGlyZWN0aW9uID0gInJpZ2h0Iiwgb2JzX3N0YXQgPSBvYnNfc3RhdCkKCmBgYAoKYGBge3J9CiMgYm9vdHN0cmFwcGVkIGh5cG90aGVzaXMKIyDOsSA9IDAuMDUKIyBIMCAtIFJhaW4gbWFrZXMgbm8gZGlmZmVyZW5jZSB0byBiaWtlIGhpcmVzCiMgSDEgLSBSYWluIGhhcyBhbiBpbXBhY3Qgb24gYmlrZSBoaXJlcwoKIyByYWluX2RheV9mbGFnIDwtIHJhaW5fZGF5ICU+JQojICAgbXV0YXRlKHJhaW5fZGF5X2ZsYWcgPSBpZl9lbHNlKHJhaW5fZGF5ID09ICJUUlVFIiwgMSwgMCkpCiMgCiMgbnVsbF9kaXN0cmlidXRpb24gPC0gcmFpbl9kYXlfZmxhZyAlPiUKIyAgIHNwZWNpZnkocmVzcG9uc2UgPSByYWluX2RheV9mbGFnKSAlPiUKIyAgIGh5cG90aGVzaXplKG51bGwgPSAicG9pbnQiLCBtdSA9IDAuMDUpICU+JQojICAgZ2VuZXJhdGUocmVwcyA9IDEwMDAwLCB0eXBlID0gImJvb3RzdHJhcCIpICU+JQojICAgY2FsY3VsYXRlKHN0YXQgPSAibWVhbiIpCiMgCiMgbnVsbF9kaXN0cmlidXRpb24gJT4lCiMgICB2aXN1YWxpc2UoKSArCiMgICBzaGFkZV9wX3ZhbHVlKGRpcmVjdGlvbiA9ICJyaWdodCIsIG9ic19zdGF0ID0gb2JzX3N0YXQpCiMgCiMgbnVsbF9kaXN0cmlidXRpb24gJT4lCiMgICBnZXRfcF92YWx1ZShkaXJlY3Rpb24gPSAicmlnaHQiLCBvYnNfc3RhdCA9IG9ic19zdGF0KQpgYGAKCiMjIyBJbmRlcGVuZGVuY2UgSHlwb3RoZXNpcyBUZXN0IE9uIFJhaW55IGRheSBkYXRhCgpEb2VzIGEgcmFpbnkgZGF5IGhhdmUgYW4gZWZmZWN0IG9uIGJpa2UgaGlyZXMKCs6xID0gMC4wNQpIMCAtIFJhaW4gbWFrZXMgbm8gZGlmZmVyZW5jZSB0byBiaWtlIGhpcmVzCkgxIC0gUmFpbiBoYXMgYW4gaW1wYWN0IG9uIGJpa2UgaGlyZXMKClRoZSBwLXZhbHVlIOKJpCDOsSwgc28gSSByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyBIMCBpbiBmYXZvdXIgb2YgdGhlIGFsdGVybmF0aXZlIGh5cG90aGVzaXMgSDEsIAp0aGF0IHJhaW4gX21heV8gaGF2ZSBhbiBlZmZlY3Qgb24gYmlrZSBoaXJlcy4KCmBgYHtyfQojIEluZGVwZW5kZW5jZSBIeXBvdGhlc2lzCiMgzrEgPSAwLjA1CiMgSDAgLSBSYWluIG1ha2VzIG5vIGRpZmZlcmVuY2UgdG8gYmlrZSBoaXJlcwojIEgxIC0gUmFpbiBoYXMgYW4gaW1wYWN0IG9uIGJpa2UgaGlyZXMKCiMgb3JnYW5pc2UgdGhlIGRhdGEgc28gSSBoYXZlIGEgcmFpbl9kYXkgY29sdW1uIHdpdGggYSBsb2dpY2FsIG91dHB1dCBUUlVFL0ZBTFNFIGlmIGl0IHJhaW5lZCB0aGF0IGRheQojIGFsc28gY291bnQgdGhlIG51bWJlciBvZiBqb3VybmV5cyB0aGF0IG9jY3VycmVkIG9uIGVhY2ggZGF5CnJhaW5fZGF5IDwtIGhpcmVzXzIwMTlfY2xlYW4gJT4lCiAgZ3JvdXBfYnkoc3RhcnRfZGF0ZSkgJT4lIAogIG11dGF0ZShyYWluX2RheSA9IHJhaW5mYWxsX21tID49IDEpICU+JSAKICBzZWxlY3Qoc3RhcnRfZGF0ZSwgcmFpbl9kYXkpICU+JSAKICBjb3VudChzdGFydF9kYXRlLCByYWluX2RheSkKCiMgY3JlYXRlIGEgbnVsbCBkaXN0cmlidXRpb24gcGVybXV0aW5nIHRoZSBUcnVlIGFuZCBGYWxzZSB2YWx1ZXMgb24gd2hldGhlciBpdCByYWluZWQKIyBkbyAxMGsgcmVwcyBhbmQgY2hlY2sgdGhlIGRpZmZlcmVuY2UgaW4gbWVhbnMgb2YgdGhlIGdyb3VwcwpudWxsX2Rpc3RyaWJ1dGlvbiA8LSByYWluX2RheSAlPiUgCiAgc3BlY2lmeShuIH4gcmFpbl9kYXkpICU+JQogIGh5cG90aGVzaXplKG51bGwgPSAiaW5kZXBlbmRlbmNlIikgJT4lIAogIGdlbmVyYXRlKHJlcHMgPSAxMDAwMCwgdHlwZSA9ICJwZXJtdXRlIikgJT4lIAogIGNhbGN1bGF0ZShzdGF0ID0gImRpZmYgaW4gbWVhbnMiLCBvcmRlciA9IGMoIlRSVUUiLCAiRkFMU0UiKSkgCgojIGNyZWF0ZSBhbiBvYnNlcnZlZCBzdGF0Cm9ic2VydmVkX3N0YXQgPC0gcmFpbl9kYXkgJT4lIAogIHNwZWNpZnkobiB+IHJhaW5fZGF5KSAlPiUKICBjYWxjdWxhdGUoc3RhdCA9ICJkaWZmIGluIG1lYW5zIiwgb3JkZXIgPSBjKCJUUlVFIiwgIkZBTFNFIikpIAoKIyBwbG90IG9ic2VydmVkIHN0YXQgb24gdGhlIG51bGwgZGlzdHJpYnV0aW9uCm51bGxfZGlzdHJpYnV0aW9uICU+JQogIHZpc3VhbGlzZSgpICsKICBzaGFkZV9wX3ZhbHVlKG9ic19zdGF0ID0gb2JzZXJ2ZWRfc3RhdCwgZGlyZWN0aW9uID0gImxlZnQiKQoKIyBjYWxjdWxhdGUgdGhlIHAtdmFsdWUgYW5kIGNvbXBhcmUgdG8gzrEgdmFsdWUKcF92YWx1ZSA8LSBudWxsX2Rpc3RyaWJ1dGlvbiAlPiUKICBnZXRfcF92YWx1ZShvYnNfc3RhdCA9IG9ic2VydmVkX3N0YXQsIGRpcmVjdGlvbiA9ICJsZWZ0IikKCnBfdmFsdWUKCmBgYAoKUmFpbnkgRGF5cyBpbiAyMDE5ID0gMTgxClJhaW55IGpvdXJuZXlzID0gNTgwNzMgKDQ2LjclKQpOb24gcmFpbnkgam91cm5leXMgPSA2NjM3MyAoNTMuMyUpCgpgYGB7cn0KIyBjb3VudCB0aGUgbnVtYmVyIG9mIGRheXMgd2l0aCByYWluZmFsbCBlcXVhbCB0byBvciBvdmVyIDFtbQpyYWluXzIwMTlfY2xlYW4gJT4lIAogIGZpbHRlcihyYWluZmFsbF9tbSA+PSAxKSAlPiUgCiAgY291bnQoKQoKIyBqb3VybmV5cyBiYXNlZCBvbiByYWluZmFsbAojIGJhc2VkIG9uIGRhaWx5IHByZWNpcGl0YXRpb24KaGlyZXNfMjAxOV9jbGVhbiAlPiUgCiAgZmlsdGVyKHJhaW5mYWxsX21tID49IDEpICU+JSAKICBjb3VudCgpCgo1ODA3MyAvIDEyNDQ0NiAqIDEwMAoKaGlyZXNfMjAxOV9jbGVhbiAlPiUgCiAgZmlsdGVyKHJhaW5mYWxsX21tIDwgMSkgJT4lIAogIGNvdW50KCkKCjY2MzczIC8gMTI0NDQ2ICogMTAwCmBgYAoKCiMjIyBUaW1lIG9mIERheSBhbmFseXNpcwoKR3ltIEJ1bm5pZXMgLSBiZWZvcmUgN2FtOiAgICAgICAgICAgNzc4MyAgIDIzLjA3IG1pbnMgICAKTW9ybmluZyBDb21tdXRlcnMgLSA3YW0gdG8gOWFtOiAgICAgMTI0NTIgIDE3Ljg3IG1pbnMgICAgCkRheSBUcmlwcGVycyAtIDlhbSB0byA1cG06ICAgICAgICAgIDY2ODgwICAyOS43NSBtaW5zICAgIApIb21ld2FyZCBCb3VuZGVycyAtIDVwbSB0byA2LjMwcG06ICAxNDk2MSAgMjMuODYgbWlucyAgICAKRXZlbmluZyBNb3ZlcnMgLSA2LjMwcG0gdG8gMTBwbTogICAgMTY4MTUgIDIzLjUgbWlucyAgICAKUHViIFBvbmllcyAtIDEwcG0gdG8gTWlkbmlnaHQ6ICAgICAgNTU1NSAgIDIwLjY3IG1pbnMgICAKCkF2ZXJhZ2Ugam91cm5leSB0aW1lIG92ZXJhbGwgaXMgMjYuMTggbWludXRlcwoKYGBge3J9CiMgR3ltIEJ1bm5pZXMgLSBiZWZvcmUgN2FtCmhpcmVzXzIwMTlfY2xlYW4gJT4lIAogIG11dGF0ZShzdGFydF90aW1lID0gYXMuY2hhcmFjdGVyKHN0YXJ0X3RpbWUpLCBlbmRfdGltZSA9IGFzLmNoYXJhY3RlcihlbmRfdGltZSkpICU+JSAKICBmaWx0ZXIoc3RhcnRfdGltZSA8PSAiMDc6MDA6MDAiKSAlPiUgCiAgbXV0YXRlKG1lYW5fZHVyYXRpb24gPSByb3VuZChtZWFuKGR1cmF0aW9uKSwgMikpICU+JSAKICBjb3VudChtZWFuX2R1cmF0aW9uKQoKIyBNb3JuaW5nIENvbW11dGVycyAtIDdhbSB0byA5YW0KaGlyZXNfMjAxOV9jbGVhbiAlPiUgCiAgbXV0YXRlKHN0YXJ0X3RpbWUgPSBhcy5jaGFyYWN0ZXIoc3RhcnRfdGltZSksIGVuZF90aW1lID0gYXMuY2hhcmFjdGVyKGVuZF90aW1lKSkgJT4lIAogIGZpbHRlcihzdGFydF90aW1lID4gIjA3OjAwOjAwIiwgc3RhcnRfdGltZSA8PSAiMDk6MDA6MDAiKSAlPiUgCiAgbXV0YXRlKG1lYW5fZHVyYXRpb24gPSByb3VuZChtZWFuKGR1cmF0aW9uKSwgMikpICU+JSAKICBjb3VudChtZWFuX2R1cmF0aW9uKQoKIyBEYXkgVHJpcHBlcnMgLSA5YW0gdG8gNXBtCmhpcmVzXzIwMTlfY2xlYW4gJT4lIAogIG11dGF0ZShzdGFydF90aW1lID0gYXMuY2hhcmFjdGVyKHN0YXJ0X3RpbWUpLCBlbmRfdGltZSA9IGFzLmNoYXJhY3RlcihlbmRfdGltZSkpICU+JSAKICBmaWx0ZXIoc3RhcnRfdGltZSA+ICIwOTowMDowMCIsIHN0YXJ0X3RpbWUgPCAiMTc6MDA6MDAiKSAlPiUgCiAgbXV0YXRlKG1lYW5fZHVyYXRpb24gPSByb3VuZChtZWFuKGR1cmF0aW9uKSwgMikpICU+JSAKICBjb3VudChtZWFuX2R1cmF0aW9uKQoKIyBIb21ld2FyZCBCb3VuZGVycyAtIDVwbSB0byA2LjMwcG0KaGlyZXNfMjAxOV9jbGVhbiAlPiUgCiAgbXV0YXRlKHN0YXJ0X3RpbWUgPSBhcy5jaGFyYWN0ZXIoc3RhcnRfdGltZSksIGVuZF90aW1lID0gYXMuY2hhcmFjdGVyKGVuZF90aW1lKSkgJT4lIAogIGZpbHRlcihzdGFydF90aW1lID49ICIxNzowMDowMCIsIHN0YXJ0X3RpbWUgPD0gIjE4OjMwOjAwIikgJT4lIAogIG11dGF0ZShtZWFuX2R1cmF0aW9uID0gcm91bmQobWVhbihkdXJhdGlvbiksIDIpKSAlPiUgCiAgY291bnQobWVhbl9kdXJhdGlvbikKCiMgRXZlbmluZyBNb3ZlcnMgLSA2LjMwcG0gdG8gMTBwbQpoaXJlc18yMDE5X2NsZWFuICU+JSAKICBtdXRhdGUoc3RhcnRfdGltZSA9IGFzLmNoYXJhY3RlcihzdGFydF90aW1lKSwgZW5kX3RpbWUgPSBhcy5jaGFyYWN0ZXIoZW5kX3RpbWUpKSAlPiUgCiAgZmlsdGVyKHN0YXJ0X3RpbWUgPiAiMTg6MzA6MDAiLCBzdGFydF90aW1lIDwgIjIyOjAwOjAwIikgJT4lIAogIG11dGF0ZShtZWFuX2R1cmF0aW9uID0gcm91bmQobWVhbihkdXJhdGlvbiksIDIpKSAlPiUgCiAgY291bnQobWVhbl9kdXJhdGlvbikKCiMgUHViIFBvbmllcyAtIDEwcG0gdG8gTWlkbmlnaHQKaGlyZXNfMjAxOV9jbGVhbiAlPiUgCiAgbXV0YXRlKHN0YXJ0X3RpbWUgPSBhcy5jaGFyYWN0ZXIoc3RhcnRfdGltZSksIGVuZF90aW1lID0gYXMuY2hhcmFjdGVyKGVuZF90aW1lKSkgJT4lIAogIGZpbHRlcihzdGFydF90aW1lID49ICIyMjowMDowMCIpICU+JSAKICBtdXRhdGUobWVhbl9kdXJhdGlvbiA9IHJvdW5kKG1lYW4oZHVyYXRpb24pLCAyKSkgJT4lIAogIGNvdW50KG1lYW5fZHVyYXRpb24pCgojIEF2ZXJhZ2Ugam91cm5leSBsZW5ndGgKaGlyZXNfMjAxOV9jbGVhbiAlPiUgCiAgbXV0YXRlKG1lYW5fZHVyYXRpb24gPSByb3VuZChtZWFuKGR1cmF0aW9uKSwgMikpICU+JSAKICBjb3VudChtZWFuX2R1cmF0aW9uKQoKYGBgCgoKYGBge3J9CmhpcmVzXzIwMTlfY2xlYW4gJT4lIAogIHNlbGVjdChzdGFydF90aW1lKSAlPiUKICBncm91cF9ieShzdGFydF90aW1lKSAlPiUgCiAgY291bnQoKSAlPiUKICBnZ3Bsb3QoKSArCiAgZ2VvbV9saW5lKGFlcyhzdGFydF90aW1lLCBuKSwgY29sID0gIiNGMjdGMUIiKSArCiAgbGFicyh4ID0gIlxuVGltZSBvZiBEYXkiLAogICAgICAgeSA9ICJOdW1iZXIgb2YgSm91cm5leXNcbiIsCiAgICAgICB0aXRsZSA9ICJTdGFydCB0aW1lIG9mIGpvdXJuZXlzIikgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUodGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgICAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwKICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwKICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSwKICAgICAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksIAogICAgICAgIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiYmxhY2siKSkKYGBgCgpgYGB7cn0KIyB0cnlpbmcgYSByYXN0ZXIgaW1hZ2Ugb2YgZWxldmF0aW9uCmdncGxvdCgpICsKICBnZW9tX3Jhc3RlcihkYXRhID0gbmV3X2VsZXZhdGlvbl9yYXN0ZXIsIGFlcyh4ID0geCwgeSA9IHkpKSArCiAgZ2VvbV9zZihkYXRhID0gZWxldmF0aW9uX3Jhc3RlciwgY29sb3IgPSAid2hpdGUiKSArCiAgY29vcmRfc2YoKSArCiAgc2NhbGVfZmlsbF92aXJpZGlzX2MoKSArCiAgbGFicyh0aXRsZSA9ICIgIiwgeCA9ICIgIiwgeSA9ICIgIiwgZmlsbCA9ICIgIikKYGBgCgo=